package org.tzw.template.utils;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.PermissionChecker;


import org.tzw.template.exception.PermissionException;
import org.tzw.template.framework.anno.AllPermission;
import org.tzw.template.framework.anno.Permissions;
import org.tzw.template.logger.LocalLogger;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;


/**
 * 作者：Administrator on 2020/8/18 10:30
 * 权限申请获取类
 */
public class PermissionManager {

    private final int mRequestCode = 10010;//权限请求码

    private static PermissionManager permissionUtil;
    private Activity context;

    private static Map<String,String> manifestMap = new ConcurrentHashMap<>();

    public static PermissionManager getInstance() {
        if (permissionUtil == null) {
            synchronized (PermissionManager.class){
                if(permissionUtil == null ){
                    permissionUtil = new PermissionManager();
                    loadManifestMap();
                }
            }
        }
        return permissionUtil;
    }

    /**
     * android 6.0 以上需要动态申请权限
     */
    public List<String> getNeedPermissions(Activity targetActivity) {
        this.context = targetActivity;
        List<String> applyList = new ArrayList<String>();
        Class<? extends Activity> targetClass = targetActivity.getClass();

        boolean hasAllPermission = targetClass.isAnnotationPresent(AllPermission.class);
        boolean hasPermissions = targetClass.isAnnotationPresent(Permissions.class);
        try {
            if(hasAllPermission){
                applyList.addAll(getPermission(targetActivity));
            }else if(hasPermissions){
                Permissions annotation = targetClass.getAnnotation(Permissions.class);
                String[] value = annotation.value();
                LocalLogger.i("PermissionManager",Arrays.asList(value).toString());
                if(value!=null&&value.length>0){
                    applyList.addAll(Arrays.asList(value));
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new PermissionException(StrUtil.format("权限请求异常:{}",e.getCause()));
        }
        return applyList;
    }

    /**
     * 检查单个权限
     *
     * @param context
     * @param permission
     * @return
     */
    public boolean checkPermission(Context context, String permission) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
        } else {
            return PermissionChecker.checkSelfPermission(context, permission) == PermissionChecker.PERMISSION_GRANTED;
        }
    }

    /**
     * 检测权限数组
     *
     * @param permissions 权限列
     * @since 2.5.0
     */
    public boolean checkPermissions(String... permissions) {
        //判断Android版本是否大于23
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            List<String> needRequestPermissionList = findDeniedPermissions(permissions);
            if (!CollUtil.isEmpty(needRequestPermissionList)) {
                ActivityCompat.requestPermissions(context, needRequestPermissionList.toArray(new String[needRequestPermissionList.size()]), mRequestCode);
                return false;
            }
        }
        return true;
    }

    /**
     * 获取集中需要申请权限的列表
     *
     * @param permissions 权限列
     * @return 全向列表
     * @since 2.5.0
     */
    private List<String> findDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissionList = new ArrayList<>();
        for (String perm : permissions) {
            if (!checkPermission(context,perm)) {
                needRequestPermissionList.add(perm);
            } else {
                if (ActivityCompat.shouldShowRequestPermissionRationale(context, perm)) {
                    needRequestPermissionList.add(perm);
                }
            }
        }
        return needRequestPermissionList;
    }

    /**
     * 检测是否说有的权限都已经授权
     *
     * @param grantResults 权限结果
     * @return 是否授权
     * @since 2.5.0
     */
    public boolean verifyPermissions(int[] grantResults) {
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }
    /**
     * 获取当前项目下所需要的动态申请的权限列表
     * @param context
     * @return
     * @throws PackageManager.NameNotFoundException
     */
    private List<String> getPermission(Context context) throws PackageManager.NameNotFoundException {
        // 获取当前应用程序的包名
        String packageName = context.getPackageName();

        // 获取PackageManager对象
        PackageManager pm = context.getPackageManager();

        // 根据包名获取应用程序的PackageInfo对象
        PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);

        // 创建存放权限字符串的集合
        ArrayList<String> permissions = new ArrayList<>();
        if(packageInfo.requestedPermissions!=null && packageInfo.requestedPermissions.length>0) {
            // 遍历PackageInfo对象中的permissions数组，将每个权限添加到集合中
            for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
                if(manifestMap.get(packageInfo.requestedPermissions[i])!=null) {
                    permissions.add(packageInfo.requestedPermissions[i]);
                }
            }
        }
        return permissions;
    }

    private static void loadManifestMap(){
        Class<Manifest.permission> permissionClass = Manifest.permission.class;
        Field[] fields = ReflectUtil.getFields(permissionClass);
        for (Field field : fields) {
            manifestMap.put(ReflectUtil.getFieldValue(permissionClass,field).toString(),field.getName());
        }
    }

    public int getRequestCode() {
        return mRequestCode;
    }
}
